package proj2501.simple_module;

import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.nio.ByteBuffer;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

import proj2501.lib.RefreshingPanel;

class P011Sound extends RefreshingPanel {
	private int samplingRate;
	private int sampleSize;
	private double frequency;
	private double position;
	private SourceDataLine line;
	private ByteBuffer buffer;
	private int total;
	public P011Sound() {
		samplingRate = 44100;
		sampleSize = 2;
		frequency = 440;
		AudioFormat format = new AudioFormat(samplingRate, 8 * sampleSize, 1, true, true);
		DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
		if (AudioSystem.isLineSupported(info)) {
			System.out.println("Supported.");
		} else {
			System.out.println("Not supported.");
		}
		try {
			line = (SourceDataLine) AudioSystem.getLine(info);
		} catch (LineUnavailableException e) {
			throw new RuntimeException();
		}
		try {
			line.open(format);
		} catch (LineUnavailableException e) {
			throw new RuntimeException();
		}
		line.start();
		buffer = ByteBuffer.allocate(line.getBufferSize());
		System.out.println("Buffer Size: " + line.getBufferSize());
		total = samplingRate * 10;
		addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_LEFT) {
					frequency /= 2;
				} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
					frequency *= 2;
				}
			}
		});
	}
	private int y;
	private boolean closed;
	private int prevFramePosition;
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		int w = getWidth();
		int h = getHeight();
		g.drawLine(0, y, w, y);
		y++;
		if (h <= y) {
			y = 0;
		}
		
		if (0 < total) {
			double increase = frequency / samplingRate;
			buffer.clear();
			int numNewSamples = line.available() / sampleSize;
			for (int i = 0; i < numNewSamples; i++) {
				buffer.putShort((short) (Short.MAX_VALUE * Math.sin(2 * Math.PI * position)));
				position += increase;
				if (1 < position) {
					position -= 1;
				}
			}
			line.write(buffer.array(), 0, buffer.position());
			total -= numNewSamples;
			if (total <= 0) {
				System.out.println("Done.");
			}
		} else {
			if (! closed) {
				int framePosition = line.getFramePosition();
				if (framePosition == prevFramePosition) {
					line.drain();
					line.close();
					closed = true;
				}
				prevFramePosition = framePosition;
			}
		}
	}
}
